﻿// Copyright: 北京经海科技有限公司
// Author: Ivan (李渊)
// Date: 2015-03-01
// Last Modified On: 2015-05-22
// Description: 辅助类，用于给图像增加标注

#ifndef DRAW_SHAPE_H
#define DRAW_SHAPE_H

#include <QObject>
#include <QPoint>
#include <QPainter>
#include <QFont>
#include <QPen>
#include <QColor>


//绘图命令
class Element : public QObject
{
public:
    enum DrawType{ NONE, LINE, CORNER, LINECORNER, PARALLEL, RCIRCLE, LCIRCLE, PCIRCLE, CURVE, POLYGON, RECTAGLE, POLYLINE, HTLINE, VTLINE };
    enum DrawState {DS_IDLE, DS_STATE1, DS_STATE2, DS_STATE3, DS_FINISH, DS_ERROR};
    Element();
    virtual ~Element() {}
    void setLinePen(QPen &pen) {m_linePen = pen;}
    void setTextFont(QFont &font) {m_textFont = font;}
    static void setScale(double scale) {m_scale = scale;}
    void textMove(const QPoint & offset){ m_textBox.translate(offset); }
    virtual int mouseLButtonPress(QPoint point) = 0;
    virtual int mouseLButtonRelease(QPoint point) = 0;
    virtual int mouseRButtonPress(QPoint point) = 0;
	virtual int mouseMove(QPoint point) = 0;
    virtual void draw( QPainter &painter ) = 0; //画方法
    virtual void updateText(void) = 0;
    enum DrawState state() const {return m_state;}
    enum DrawType type() const {return m_drawType;}
    bool isInTextBox(const QPoint & point) const {return m_textBox.contains(point);}
protected:	
    virtual void computeBox(void) = 0;
    void updateTextPos();
protected:
	enum DrawType m_drawType;//图形样式
	enum DrawState m_state; // 元素是否绘制结束
	QRect m_box;//最小包围盒  
	QPen m_linePen;//线的颜色
	bool m_isPicked; // 判断是否被选择
    QString m_text;
    QFont m_textFont;  //文字的字体
    QRect m_textBox;
    static double m_scale; // 像素尺寸，该尺寸由定标操作得到
    //static double m_zoomFactor; // DisplayWidget 放缩时标注也要相应的放缩，但是文字大小不变
};


class DrawLine:public Element
{
public:
    DrawLine(void);
    ~DrawLine(void) {}
    void build(QPoint start, QPoint end);
    int mouseLButtonPress(QPoint point);
    int mouseLButtonRelease(QPoint /*point*/);
    int mouseRButtonPress(QPoint /*point*/){return 0;}
    int mouseMove(QPoint point);
    void draw( QPainter &painter ); //画方法
    void updateText(void);
    double getLength() {return m_length;}
private:
    QPoint m_start; // 开始点
    QPoint m_end;   // 结束点

    //为了出现标尺的图形，还得加上四个标尺的坐标
    QPoint m_line1_start;
    QPoint m_line1_end;
    QPoint m_line2_start;
    QPoint m_line2_end;

    double m_length;//标尺的长度，以像素为单位
    double m_cos_theta;
    double m_sin_theta;
private:
    void setStartPoint(QPoint point);
    void setTempEndPoint(QPoint point);
    void setEndPoint(QPoint point);
    virtual void computeBox();
    void compute(void);
    void computeLength(void); // 得到线段的长度
};

class DrawPolyline:public Element
{
public:
    DrawPolyline(void);
    ~DrawPolyline(void) {}
    void build(QVector<QPoint> points);
    int mouseLButtonPress(QPoint point);
    int mouseRButtonPress(QPoint point);
    int mouseLButtonRelease(QPoint /*point*/){return 0;}
    int mouseMove(QPoint point);
    void draw( QPainter &painter ); //画方法
    void updateText(void);
    double getLength() {return m_length;}
private:
    QVector<QPoint> m_points; // 开始点
    QPoint m_tempEnd;
    double m_length;//标尺的长度，以像素为单位
private:
    void setStartPoint(QPoint point);
    void setMidPoint(QPoint point);
    void setTempEndPoint(QPoint point);
    void setEndPoint(QPoint point);
    virtual void computeBox();
    void compute(void);
    void computeLength(void); // 得到线段的长度
};

class DrawPolygon:public Element
{
public:
    DrawPolygon(void);
    ~DrawPolygon(void) {}
    void build(QVector<QPoint> points);
    int mouseLButtonPress(QPoint point);
    int mouseRButtonPress(QPoint point);
    int mouseLButtonRelease(QPoint /*point*/){return 0;}
    int mouseMove(QPoint point);
    void draw( QPainter &painter ); //画方法
    void updateText(void);
    double getArea() {return m_area;}
private:
    QVector<QPoint> m_points; // 开始点
    QPoint m_tempEnd;
    double m_area;//区域的面积，以像素为单位
private:
    void setStartPoint(QPoint point);
    void setMidPoint(QPoint point);
    void setTempEndPoint(QPoint point);
    void setEndPoint(QPoint point);
    virtual void computeBox();
    void compute(void);
};

class HTLine:public DrawLine
{
public:
    HTLine(void);
    int mouseLButtonPress(QPoint point);
    int mouseLButtonRelease(QPoint /*point*/);
    int mouseRButtonPress(QPoint /*point*/){return 0;}
    int mouseMove(QPoint);
    static void setHLine(int hline) {m_hline = hline;}
private:
    static int m_hline;
};
class VTLine:public DrawLine
{
public:
    VTLine(void);
    int mouseLButtonPress(QPoint point);
    int mouseLButtonRelease(QPoint /*point*/);
    int mouseRButtonPress(QPoint /*point*/){return 0;}
    int mouseMove(QPoint point);
    static void setVLine(int vline) {m_vline = vline;}
private:
    static int m_vline;
};
class DrawParallelLine :public Element
{
public:
	DrawParallelLine(void);
    ~DrawParallelLine(void) {}
    void build(QPoint p1, QPoint p2, QPoint p3);
    int mouseLButtonPress(QPoint point);
    int mouseLButtonRelease(QPoint point);
    int mouseRButtonPress(QPoint /*point*/){return 0;}
    int mouseMove(QPoint point);
    void draw( QPainter &painter ); //画方法
    void updateText(void);
    double getLength() {return m_distance;}
private:
	QPoint m_line1_start;
	QPoint m_line1_end;
	QPoint m_line2_start;
	QPoint m_line2_end;	

	double m_length;//标尺的长度
	double m_distance;// 平行线间距
	double m_cos_theta;
	double m_sin_theta;

private: 
    void setStartPoint(QPoint point);
    void setEndPoint(QPoint point);
    void setTempEndPoint(QPoint point);
    void setSecondLine(QPoint point);
    void setTempSecondLine(QPoint point);
	virtual void computeBox();
	void computeLengthSlope(void);
	void computeDist(void); // 得到线段间的距离

};

//DrawRCircle 给定圆心和半径
class DrawRCircle :public Element
{
public:
    DrawRCircle(void);
    ~DrawRCircle(void){}
    void build(QPoint center, double radius);
    int mouseLButtonPress(QPoint point);
    int mouseLButtonRelease(QPoint /*point*/);
    int mouseRButtonPress(QPoint /*point*/){return 0;}
    int mouseMove(QPoint point);
    void draw( QPainter &painter ); //画方法
    void updateText(void);
    double getDiameter() {return m_radius * 2;}
private:
    QPoint m_centre;
    double m_radius;

private:
    virtual void computeBox();
    void setCentre(QPoint point);
    void setRadius(double r);
    void setTempRadius(double r);
};

class DrawLCircle :public Element
{
public:
    DrawLCircle(void);
    ~DrawLCircle(void);
    void build(QPoint p1, QPoint p2);
    int mouseLButtonPress(QPoint point);
    int mouseLButtonRelease(QPoint /*point*/);
    int mouseRButtonPress(QPoint /*point*/){return 0;}
    int mouseMove(QPoint point);
    void draw( QPainter &painter ); //画方法
    void updateText(void);
    double getDiameter() {return m_radius * 2;}
private:
    QPoint m_start;
    QPoint m_end;
    QRect m_box;
    QPoint m_centre;
    double m_radius;

private:
    void setStartPoint(QPoint start);
    void setEndPoint(QPoint end);
    void setTempEndPoint(QPoint end);
    virtual void computeBox();
};

class DrawRect :public Element
{
public:
    DrawRect(void);
    ~DrawRect(void);
    void build(QPoint start, QPoint end);
    int mouseLButtonPress(QPoint point);
    int mouseLButtonRelease(QPoint /*point*/);
    int mouseRButtonPress(QPoint /*point*/){return 0;}
    int mouseMove(QPoint point);
    void draw( QPainter &painter ); //画方法
    void updateText(void);
private:
    QPoint m_start;
    QPoint m_end;
    QRect m_rect;
    double m_area;

private:
    virtual void computeBox();
    void setStartPoint(QPoint point);
    void setTempEndPoint(QPoint point);
    void setEndPoint(QPoint point);
};

class DrawCorner :public Element
{
public:
    DrawCorner(void);
    ~DrawCorner(void);
    void build(QPoint start, QPoint second, QPoint end);
    int mouseLButtonPress(QPoint point);
    int mouseLButtonRelease(QPoint /*point*/);
    int mouseRButtonPress(QPoint /*point*/){return 0;}
    int mouseMove(QPoint point);
    void draw( QPainter &painter ); //画方法
    void updateText(void);
private:
    QPoint m_start;
    QPoint m_mid;
    QPoint m_end;
    double m_angle;

private:
    void setStartPoint(QPoint start);
    void setSecondPoint(QPoint second);
    void setEndPoint(QPoint end);
    virtual void computeBox();
    void computeAngle(void);
};


class DrawLCorner:public Element
{
public:
    DrawLCorner(void);
    ~DrawLCorner(void);
    void setStartPoint(QPoint point);
    void setEndPoint(QPoint point);
    int mouseLButtonPress(QPoint point);
    int mouseLButtonRelease(QPoint /*point*/);
    int mouseRButtonPress(QPoint /*point*/){return 0;}
    int mouseMove(QPoint point);
    void draw( QPainter &painter ); //画方法
    void updateText(void);
private:
    QPoint m_line1_start; // 开始点
    QPoint m_line1_end;   // 结束点
    QPoint m_line2_start; // 开始点
    QPoint m_line2_end;   // 结束点

    double m_length;//标尺的长度
//	double m_slope;//标尺的斜率
    double m_cos_theta;
    double m_sin_theta;

private:
    virtual void computeBox();

    void compute(void);
    void computeAngle();
    // 得到线段的长度
    void computeLength(void);
};

class DrawPCIRCLE:public Element
{
public:
    DrawPCIRCLE(void);
    ~DrawPCIRCLE(void);
    void build(QPoint p1,QPoint p2,QPoint p3);
    int mouseLButtonPress(QPoint point);
    int mouseRButtonPress(QPoint point);
    int mouseLButtonRelease(QPoint ){return 0;}
    int mouseMove(QPoint ){return 0;}
    void draw( QPainter &painter ); //画方法
    void updateText(void);
    double getDiameter() {return m_radius * 2;}

private:
    QPoint m_start;
    QPoint m_middle;
    QPoint m_end;
    QPoint m_centre;
    double m_radius;

    virtual void computeBox();
    void compute();

};

#endif
